package com.stars.easyms.schedule.util;

import java.util.LinkedList;
import java.util.List;

/**
 * 计时器
 *
 * @author guoguifang
 */
public class StopWatch {

    private final List<TaskInfo> taskList;
    private long startTimeMillis;
    private String currentTaskName;
    private StopWatch.TaskInfo lastTaskInfo;
    private int taskCount;
    private long totalTimeMillis;

    public StopWatch() {
        this.taskList = new LinkedList<>();
    }

    public void start() throws IllegalStateException {
        this.start("");
    }

    public void start(String taskName) throws IllegalStateException {
        if (this.currentTaskName != null) {
            throw new IllegalStateException("Can't start StopWatch: it's already running");
        } else {
            this.currentTaskName = taskName;
            this.startTimeMillis = System.currentTimeMillis();
        }
    }

    public long getStartTimeMillis() {
        if (this.currentTaskName == null) {
            throw new IllegalStateException("Can't get StopWatch startTimeMillis: it's not running");
        }
        return startTimeMillis;
    }

    public void stop() throws IllegalStateException {
        if (this.currentTaskName == null) {
            throw new IllegalStateException("Can't stop StopWatch: it's not running");
        } else {
            long stopTimeMillis = System.currentTimeMillis();
            long usedTimeMillis = stopTimeMillis - this.startTimeMillis;
            this.totalTimeMillis += usedTimeMillis;
            this.lastTaskInfo = new StopWatch.TaskInfo(this.currentTaskName, this.startTimeMillis, stopTimeMillis, usedTimeMillis);
            this.taskList.add(this.lastTaskInfo);
            ++this.taskCount;
            this.currentTaskName = null;
        }
    }

    public boolean isRunning() {
        return this.currentTaskName != null;
    }

    public String currentTaskName() {
        return this.currentTaskName;
    }

    public long getLastTaskUsedTimeMillis() throws IllegalStateException {
        if (this.lastTaskInfo == null) {
            throw new IllegalStateException("No tasks run: can't get last task interval");
        } else {
            return this.lastTaskInfo.getUsedTimeMillis();
        }
    }

    public String getLastTaskName() throws IllegalStateException {
        if (this.lastTaskInfo == null) {
            throw new IllegalStateException("No tasks run: can't get last task name");
        } else {
            return this.lastTaskInfo.getTaskName();
        }
    }

    public StopWatch.TaskInfo getLastTaskInfo() throws IllegalStateException {
        if (this.lastTaskInfo == null) {
            throw new IllegalStateException("No tasks run: can't get last task info");
        } else {
            return this.lastTaskInfo;
        }
    }

    public long getTotalTimeMillis() {
        return this.totalTimeMillis;
    }

    public double getTotalTimeSeconds() {
        return (double) this.totalTimeMillis / 1000.0D;
    }

    public int getTaskCount() {
        return this.taskCount;
    }

    public StopWatch.TaskInfo[] getTaskInfo() {
        return this.taskList.toArray(new StopWatch.TaskInfo[this.taskList.size()]);
    }

    public static final class TaskInfo {
        private final String taskName;
        private final long startTimeMillis;
        private final long stopTimeMillis;
        private final long usedTimeMillis;

        TaskInfo(String taskName, long startTimeMillis, long stopTimeMillis, long usedTimeMillis) {
            this.taskName = taskName;
            this.startTimeMillis = startTimeMillis;
            this.stopTimeMillis = stopTimeMillis;
            this.usedTimeMillis = usedTimeMillis;
        }

        public String getTaskName() {
            return this.taskName;
        }

        public long getStartTimeMillis() {
            return startTimeMillis;
        }

        public long getStopTimeMillis() {
            return stopTimeMillis;
        }

        public long getUsedTimeMillis() {
            return this.usedTimeMillis;
        }

        public double getUsedTimeSeconds() {
            return (double) this.usedTimeMillis / 1000.0D;
        }
    }
}
